package com.cx.base.day14_channel.nio_02_zeroCopy.baseMmap2Zero;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author: robert.song
 * @Date: Created in 2022/4/24
 */
public class UseMethod_TransferToAndTransferFrom {

    public static void main(String[] args) {
        String url = ".\\test.rar";
        String copyUrl = ".\\test_byZeroCopy.rar";
        try {
            File testFile = new File(url);
//            获取文件字节数量
            long size = testFile.length();
            System.out.println(size);
            //定义每个线程处理的文件大小
            long maxHandleSizeEveryThread = 20 * 1024 * 1024;// 20M
            //定义线程池  控制同时处理的线程数 可以避免磁盘占用过高
            ExecutorService fixedThreadPool = Executors.newFixedThreadPool(50);
            //计算需要多少线程处理
            long threadCount = size % maxHandleSizeEveryThread == 0 ? size / maxHandleSizeEveryThread : size / maxHandleSizeEveryThread + 1;

            System.out.println("需要线程数:" + threadCount);

            CountDownLatch cdl = new CountDownLatch((int) threadCount);

            for (long i = 0, position = 0; i < threadCount; i++, position = i * maxHandleSizeEveryThread) {
                if (size - position < maxHandleSizeEveryThread) {
                    maxHandleSizeEveryThread = size - position;
                }
                fixedThreadPool.execute(new FileThread(url, copyUrl, position, maxHandleSizeEveryThread, cdl));
            }
            cdl.await();
            System.out.println(cdl.getCount());
            System.out.println("文件复制完毕");
            fixedThreadPool.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static class FileThread extends Thread {

        private String fileUrl;
        private String copyUrl;
        private long position;
        private long count;
        private CountDownLatch cdl;

        public FileThread(String fileUrl, String copyUrl, long position, long count, CountDownLatch cdl) {
            this.fileUrl = fileUrl;
            this.copyUrl = copyUrl;
            this.position = position;
            this.count = count;
            this.cdl = cdl;
        }

        @Override
        public void run() {
            RandomAccessFile fileRaf = null;
            RandomAccessFile copyRaf = null;
            FileChannel fileChannel = null;
            FileChannel copyChannel = null;
            try {
                fileRaf = new RandomAccessFile(new File(fileUrl), "rw");
                copyRaf = new RandomAccessFile(new File(copyUrl), "rw");

                fileChannel = fileRaf.getChannel();
                copyChannel = copyRaf.getChannel();

                copyChannel.position(position);
                fileChannel.position(position);

                //1、transferTo零拷贝
                fileChannel.transferTo(position, count, copyChannel);
//                2、transferFrom零拷贝
                copyChannel.transferFrom(fileChannel, position, count);

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                cdl.countDown();
                closeStream(copyChannel, fileChannel, copyRaf, fileRaf);
            }
        }
    }

    //关闭流
    public static void closeStream(Closeable... closeables) {
        for (Closeable closeable : closeables) {
            if (closeable != null) {
                try {
                    closeable.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
